home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / music_utilities / pt013.dms / pt013.adf / Programmers / MODPlayer / modplayer.a < prev    next >
Text File  |  1991-08-25  |  58KB  |  2,102 lines

  1. ;    modplayer.a
  2. ;    ~~~~~~~~~~~
  3. ; The music player routine for MED V3.20 (and OctaMED V2.0 4-channel) songs.
  4. ; Written by Teijo Kinnunen.
  5.  
  6. ;============================================================================
  7.  
  8. MIDI    EQU    0    ;1 = include MIDI code
  9. AUDDEV    EQU    1    ;1 = allocate channels using audio.device
  10. SYNTH    EQU    1    ;1 = include synth-sound handler
  11. CHECK    EQU    1    ;1 = do range checkings (track, sample in mem etc.)
  12. RELVOL    EQU    1    ;1 = include relative volume handling code
  13. IFF53    EQU    1    ;1 = play IFF 3- and 5-octave samples correctly
  14. HOLD    EQU    1    ;1 = handle hold/decay
  15. ;****** Timing control ******
  16. VBLANK    EQU    0    ;1 = use VBlank interrupt (when absolutely necessary)
  17. CIAB    EQU    1    ;1 = use CIAB timers (default)
  18. ; Please use CIAB whenever possible to avoid problems with variable
  19. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  20. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  21. ; then you just call _IntHandler for each timing pulse.
  22.  
  23. ;============================================================================
  24.  
  25. ;If you are making a demo/game with only a single tune you'd like to
  26. ;incorporate in the code (like "easyplayer.a" of MED V3), set the following
  27. ;flag to 1. This requires an assembler with INCBIN (or equivalent) directive.
  28. ;You have to type the module name into the INCBIN statement (located near the
  29. ;end of this file, on line 2044).
  30.  
  31. EASY    EQU    0
  32.  
  33. ;Call _startmusic to play the music, and _endmusic to stop it (before
  34. ;exiting). Note: don't call _startmusic twice!! This would cause the module
  35. ;to be relocated twice (= Guru). If you need to stop and continue playing,
  36. ;don't use the EASY routines, use PlayModule/StopPlayer... instead.
  37.  
  38. ;============================================================================
  39.  
  40. ;the MMD0 structure offsets
  41. mmd_id        EQU    0
  42. mmd_modlen    EQU    4
  43. mmd_songinfo    EQU    8
  44. mmd_songlen    EQU    12    ;currently unused
  45. mmd_blockarr    EQU    16
  46. mmd_blockarrlen    EQU    20
  47. mmd_smplarr    EQU    24
  48. mmd_smplarrlen    EQU    28
  49. mmd_expdata    EQU    32
  50. mmd_expsize    EQU    36
  51. mmd_pstate    EQU    40 ; <0 = play song, 0 = don't play, >0 = play block
  52. mmd_pblock    EQU    42
  53. mmd_pline    EQU    44
  54. mmd_pseqnum    EQU    46
  55. mmd_actplayline    EQU    48
  56. mmd_counter    EQU    50
  57. mmd_songsleft    EQU    51
  58.  
  59. ;the MMD0song structure
  60. ;Instrument data here (504 bytes = 63 * 8)
  61. msng_numblocks    EQU    504
  62. msng_songlen    EQU    506
  63. msng_playseq    EQU    508
  64. msng_deftempo    EQU    764
  65. msng_playtransp    EQU    766
  66. msng_flags    EQU    767
  67. msng_reserved    EQU    768
  68. msng_tempo2    EQU    769
  69. msng_trkvol    EQU    770
  70. msng_mastervol    EQU    786
  71. msng_numsamples    EQU    787
  72.  
  73. ;Instrument data
  74. inst_repeat    EQU    0
  75. inst_replen    EQU    2
  76. inst_midich    EQU    4
  77. inst_midipreset    EQU    5
  78. inst_svol    EQU    6
  79. inst_strans    EQU    7
  80.  
  81. ;Audio hardware offsets
  82. ac_ptr    EQU    $00
  83. ac_len    EQU    $04
  84. ac_per    EQU    $06
  85. ac_vol    EQU    $08
  86.  
  87. ;Trackdata sizes
  88. T03SZ    EQU    88
  89. T415SZ    EQU    18
  90.  
  91.         section    "text",code
  92.  
  93.     IFNE    EASY
  94.  
  95.         xdef    _startmusic,_endmusic
  96.  
  97. _startmusic    lea    easymod,a0
  98.         bsr.w    _RelocModule
  99.         bsr.w    _InitPlayer
  100.         lea    easymod,a0
  101.         bra.w    _PlayModule
  102.  
  103. _endmusic    bra.w    _RemPlayer
  104.     ENDC
  105.  
  106.  
  107.  
  108. _ChannelOff:    ;d0 = channel #
  109.         lea    trackdataptrs(pc),a1
  110.         lsl.b    #2,d0
  111.         adda.w    d0,a1
  112.         lsr.b    #2,d0
  113.         movea.l    (a1),a1
  114.     IFNE    MIDI
  115.         move.b    trk_prevmidin(a1),d1    ;is it MIDI??
  116.         beq.s    notcomidi        ;not a MIDI note
  117. choff_midi:    clr.b    trk_prevmidin(a1)
  118.         lea    noteondata(pc),a0
  119.         move.b    d1,1(a0)
  120.         move.b    trk_prevmidich(a1),(a0)    ;prev MIDI channel
  121.         clr.b    2(a0)
  122.         or.b    #$90,(a0)        ;note off
  123.         moveq    #3,d0
  124.         bra.w    _AddMIDIData
  125.     ENDC
  126. notcomidi:    cmp.b    #4,d0
  127.         bge.s    notamigatrk
  128.     IFNE    SYNTH
  129.         clr.l    trk_synthptr(a1)
  130.         clr.b    trk_synthtype(a1)
  131.     ENDC
  132.         moveq    #1,d1
  133.         lsl.w    d0,d1
  134.         move.w    d1,$dff096
  135. notamigatrk:    rts
  136.  
  137. SoundOff:    move.l    d2,-(sp)
  138.         moveq    #15,d2
  139. SO_loop0    move.l    d2,d0
  140.         bsr.s    _ChannelOff
  141.         dbf    d2,SO_loop0
  142.         lea    _module(pc),a0
  143.         clr.l    (a0)        ;play nothing
  144.         move.l    (sp)+,d2
  145.         rts
  146.  
  147. _PlayNote:    ;d0(w) = trk #, d1 = note #, d2 = vol, d3(w) = instr # a3 = addr of instr
  148.         moveq    #0,d4
  149.         bset    d0,d4    ;d4 is mask for this channel
  150.         movea.l    mmd_smplarr(a6),a0
  151.         add.w    d3,d3            ;d3 = instr.num << 2
  152.         add.w    d3,d3
  153.         move.l    0(a0,d3.w),d5        ;get address of instrument
  154.     IFNE    MIDI
  155.         bne.s    inmem
  156.         tst.b    inst_midich(a3)        ;is MIDI channel set
  157.     ENDC
  158.     IFNE    CHECK
  159.         beq.w    pnote_rts        ; NO!!!
  160.     ENDC
  161. inmem:        add.b    msng_playtransp(a4),d1    ;add play transpose
  162.         add.b    inst_strans(a3),d1    ;and instr. transpose
  163.         cmp.b    #4,d0
  164.         bge.s    nodmaoff    ;track # >= 4: not an Amiga channel
  165.         move.l    d5,a1
  166.     IFNE    SYNTH
  167.         tst.l    d5
  168.         beq.s    stpdma
  169.         tst.b    trk_synthtype(a5)
  170.         ble.s    stpdma        ;prev. type = sample/hybrid
  171.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  172.         beq.s    nostpdma
  173.     ENDC
  174. stpdma:        move.w    d4,$dff096        ;stop this channel (dmacon)
  175. nostpdma:
  176.     IFNE    SYNTH
  177.         clr.l    trk_synthptr(a5)
  178.     ENDC
  179. nodmaoff:
  180.     IFNE    MIDI
  181.         move.b    trk_prevmidin(a5),d3    ;get prev. midi note
  182.         beq.s    noprevmidi
  183.         clr.b    trk_prevmidin(a5)
  184.         lea    noteondata+2(pc),a0
  185.         clr.b    (a0)                ;volume = 0
  186.         move.b    d3,-(a0)
  187.         move.b    trk_prevmidich(a5),-(a0)    ;prev midi channel
  188.         or.b    #$90,(a0)            ;note off
  189.         movem.w    d0-d1,-(sp)
  190.         moveq    #3,d0
  191.         bsr.w    _AddMIDIData
  192.         movem.w    (sp)+,d0-d1
  193. noprevmidi:    tst.b    inst_midich(a3)
  194.         bne.w    handleMIDInote
  195.     ENDC
  196.     IFNE    CHECK
  197.         cmp.w    #4,d0        ;track > 3???
  198.         bge.w    pnote_rts    ;no Amiga instruments here!!!
  199.     ENDC
  200. ; handle decay (for tracks 0 - 3 only!!)
  201.     IFNE    HOLD
  202.         clr.b    trk_fadespd(a5)        ;no fade yet..
  203.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  204.     ENDC
  205.         clr.b    trk_vibroffs(a5)    ;clr vibrato offset
  206.         or.w    d4,dmaonmsk
  207.         move.l    d5,a0
  208.         subq.b    #1,d1
  209.     IFNE    SYNTH
  210.         tst.w    4(a0)
  211.         bmi.w    handleSynthnote
  212.         clr.b    trk_synthtype(a5)
  213.     ENDC
  214. tlwtst0:    tst.b    d1
  215.         bpl.s    notenot2low
  216.         add.b    #12,d1    ;note was too low, octave up
  217.         bra.s    tlwtst0
  218. notenot2low:    cmp.b    #62,d1
  219.         ble.s    endpttest
  220.         sub.b    #12,d1    ;note was too high, octave down
  221. endpttest:
  222.         moveq    #0,d4
  223.     IFNE    IFF53
  224.         move.w    4(a0),d0    ;Soitin-struct in a0
  225.         bne.s    iff5or3oct    ;note # in d1 (0 - ...)
  226.     ENDC
  227.         move.l    a0,d0
  228.         lea    _periods(pc),a0
  229.         move.l    a0,trk_periodtbl(a5)
  230.         add.b    d1,d1
  231.         move.w    0(a0,d1.w),d5 ;put period to d5
  232.         move.l    d0,a0
  233.         addq.l    #6,d0        ;Skip structure
  234.         move.l    (a0),d1        ;length
  235.         move.w    (a3),d4        ;inst_repeat
  236.         move.w    inst_replen(a3),d3
  237.     IFNE    IFF53
  238.         bra.s    end_getdata
  239. shiftcnt    dc.b    4,3,2,1,1,0,2,2,1,1,0,0
  240. mullencnt    dc.b    15,7,3,1,1,0,3,3,1,1,0,0
  241. octstart    dc.b    12,12,12,12,24,24,0,12,12,24,24,36
  242. iff5or3oct:    movem.l    d6-d7,-(sp)
  243.         moveq    #0,d7
  244.         move.w    d1,d7
  245.         divu    #12,d7    ;octave #
  246.         move.l    d7,d5
  247.         swap    d5    ;note number in this oct (0-11) is in d5
  248.         move.l    (a0),d1
  249.         cmp.b    #2,d0
  250.         bne.s    no3oct
  251.         addq.l    #6,d7
  252.         divu    #7,d1    ;get length of the 1st octave
  253.         bra.s    no5oct
  254. no3oct:        divu    #31,d1    ;get length of the 1st octave (5 octaves)
  255. no5oct:        move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  256.         move.w    (a3),d4        ;inst_repeat
  257.         move.w    inst_replen(a3),d3
  258.         moveq    #0,d6
  259.         move.b    shiftcnt(pc,d7.w),d6
  260.         lsl.w    d6,d4
  261.         lsl.w    d6,d3
  262.         lsl.w    d6,d1
  263.         move.b    mullencnt(pc,d7.w),d6
  264.         mulu    d6,d0        ;offset of this oct from 1st oct
  265.         add.l    a0,d0        ;add base address to offset
  266.         addq.l    #6,d0        ;skip structure
  267.         lea    _periods(pc),a1
  268.         add.b    octstart(pc,d7.w),d5
  269.         add.b    d5,d5
  270.         move.w    0(a1,d5.w),d5
  271.         movem.l    (sp)+,d6-d7
  272.     ENDC
  273. end_getdata    movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  274.         move.l    d0,(a1)+        ;put it in ac_ptr (= 0)
  275.         cmp.w    #1,d3
  276.         bhi.s    repeat
  277.         
  278.         move.l    #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  279.         move.w    #1,trk_samplelen(a5)    ;length: 1 word
  280.         lsr.l    #1,d1            ;shift length right
  281.         move.w    d1,(a1)+    ;and put to custom chip (ac_len)
  282.         bra.s    retsn1
  283.  
  284. repeat:        tst.w    d4
  285.         beq.s    begin0        ;rep. start < 2
  286.         move.w    d4,(a1)+    ;move repeat to hardware
  287.         bra.s    beginn0
  288. begin0:        move.w    d3,(a1)+    ;ac_len
  289. beginn0:    add.l    d4,d4        ;shift
  290.         add.l    d4,d0        ;d0 = starting address of repeat
  291.         move.l    d0,trk_sampleptr(a5)    ;remember rep. start
  292.         move.w    d3,trk_samplelen(a5)    ;remember rep. length
  293.                 
  294. retsn1:        move.w    d5,(a1)+ ;getinsdata puts period to d5 (a1 = ac_per)
  295.         move.w    d2,(a1)    ;a1 = ac_vol
  296.         move.w    d5,trk_prevper(a5)
  297.     IFNE    SYNTH
  298.         tst.b    trk_synthtype(a5)
  299.         bne.w    hSn2
  300.     ENDC
  301. pnote_rts    rts
  302.  
  303.     IFNE    MIDI
  304. handleMIDInote:    add.b    #23,d1        ;2 octaves higher and -1
  305.         bpl.s    hmn_not2low    ;note number not too low
  306. hmn_2low    add.b    #12,d1        ;it was too low, 1 octave up
  307.         bmi.s    hmn_2low
  308. hmn_not2low
  309.         add.b    d2,d2        ;volume 0 - 63 => 0 - 127
  310.         subq.b    #1,d2        ;if 128 => 127
  311.         bpl.s    hmn_notvolu0
  312.         moveq    #0,d2
  313. hmn_notvolu0
  314.         moveq    #0,d5
  315.         move.b    inst_midich(a3),d5    ;get midi chan of this instrument
  316.         bpl.s    hmn_nosmof    ;bit 7 clear
  317.         clr.b    trk_prevmidin(a5)    ;suppress note off!
  318.         and.b    #$1F,d5        ;clear all flag bits etc...
  319.         bra.s    hmn_smof
  320. hmn_nosmof    move.b    d1,trk_prevmidin(a5)
  321. hmn_smof    subq.b    #1,d5        ;from 1-16 to 0-15
  322.         move.b    d5,trk_prevmidich(a5)    ;save to prev midi channel
  323.  
  324.         move.b    inst_midipreset(a3),d0    ;get preset #
  325.         beq.s    nochgpres    ;zero = no preset
  326.         cmp.b    prevmidicpres(pc,d5.w),d0    ;is this previous preset ??
  327.         beq.s    nochgpres    ;yes...no need to change
  328.         lea    prevmidicpres(pc,d5.w),a1
  329.         move.b    d0,(a1)        ;save preset to prevmidicpres
  330.         subq.b    #1,d0        ;sub 1 to get 0 - 127
  331.         lea    preschgdata+1(pc),a0
  332.         move.b    d0,(a0)        ;push the number to second byte
  333.         move.b    #$c0,-(a0)    ;command: $C
  334.         or.b    d5,(a0)        ;"or" midi channel
  335.         moveq    #2,d0
  336.         move.w    d1,-(sp)
  337.         bsr.w    _AddMIDIData
  338.         move.w    (sp)+,d1
  339.         tst.b    d2
  340.         beq.s    hmn_suppress    ;vol = 0, don't send NOTE ON
  341.  
  342. nochgpres    lea    bytesinnotebuff(pc),a0
  343.         movea.l    a0,a1
  344.         adda.w    (a0)+,a0
  345.         or.b    #$90,d5        ;MIDI: Note on
  346.         move.b    d5,(a0)+    ;MIDI msg Note on & channel
  347.         move.b    d1,(a0)+    ;MIDI msg note #
  348.         move.b    d2,(a0)        ;MIDI msg volume
  349.         beq.s    hmn_suppress    ;vol = 0 -> no note
  350.         addq.w    #3,(a1)
  351.         rts
  352. hmn_suppress    clr.b    trk_prevmidin(a5)
  353.         rts
  354.  
  355. prevmidicpres:    dc.l    0,0,0,0 ; 16 bytes
  356.     ENDC
  357.  
  358.     IFNE    SYNTH
  359. handleSynthnote:
  360.         move.b    d1,trk_prevnote2(a5)
  361.         move.l    a0,trk_synthptr(a5)
  362.         cmp.w    #-2,4(a0)    ;HYBRID??
  363.         bne.s    hSn_nossn
  364.         st    trk_synthtype(a5)
  365.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  366.         bra.w    tlwtst0        ;go and play it
  367. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  368.         lea    _synthper(pc),a1
  369.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  370.         add.w    d1,d1
  371.         move.w    0(a1,d1.w),d1
  372.         movea.l    trk_audioaddr(a5),a1
  373.         move.w    d1,trk_prevper(a5)
  374.         move.w    d1,ac_per(a1)
  375.         clr.l    trk_sampleptr(a5)
  376. hSn2:        lea    trk_arpgoffs(a5),a1
  377.         clr.l    (a1)+
  378.         clr.l    (a1)+
  379.         clr.l    (a1)+
  380.         clr.l    (a1)+
  381.         clr.l    (a1)+
  382.         clr.l    (a1)+
  383.         move.l    #sinetable,(a1)+
  384.         clr.w    (a1)+
  385.         movea.l    trk_synthptr(a5),a0
  386.                 move.w    18(a0),(a1)+
  387.                 clr.b    (a1)
  388.                 cmp.b    #$E,trk_cmd(a5)
  389.                 bne.s    synth_start
  390.                 move.b    trk_cmdqual(a5),trk_wfcmd+1(a5)
  391.  
  392. synth_start:    move.l    a3,-(sp)
  393.         movea.l    trk_audioaddr(a5),a3    ;audio channel base address
  394.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  395.         bgt.w    synth_wftbl        ;not 0...go to waveform
  396.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  397.         move.b    trk_volchgspd(a5),d0    ;volume change??
  398.         beq.s    synth_nochgvol        ;no.
  399.         add.b    trk_synvol(a5),d0    ;add previous volume
  400.         bpl.s    synth_voln2l        ;not negative
  401.         moveq    #0,d0            ;was negative => 0
  402. synth_voln2l:    cmp.b    #$40,d0            ;too high??
  403.         ble.s    synth_voln2h        ;not 2 high.
  404.         moveq    #$40,d0            ;was 2 high => 64
  405. synth_voln2h:    move.b    d0,trk_synvol(a5)    ;remember new...
  406.         move.b    d0,ac_vol+1(a3)        ;and change it
  407. synth_nochgvol:    move.l    trk_envptr(a5),d1    ;envelope pointer
  408.         beq.s    synth_novolenv
  409.         movea.l    d1,a1
  410.         move.b    (a1)+,d0
  411.         add.b    #128,d0
  412.         lsr.b    #2,d0
  413.         move.b    d0,trk_synvol(a5)
  414.         move.b    d0,ac_vol+1(a3)
  415.         addq.b    #1,trk_envcount(a5)
  416.         bpl.s    synth_endenv
  417.         clr.b    trk_envcount(a5)
  418.         move.l    trk_envrestart(a5),a1
  419. synth_endenv    move.l    a1,trk_envptr(a5)
  420. synth_novolenv    move.w    trk_volcmd(a5),d0    ;get table position ptr
  421.         tst.b    trk_volwait(a5)        ;WAI(t) active
  422.         beq.s    synth_getvolcmd        ;no
  423.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  424.         ble.s    synth_getvolcmd        ;0 => continue
  425.         bra.w    synth_wftbl        ;> 0 => still wait
  426. synth_inccnt:    addq.b    #1,d0
  427. synth_getvolcmd:
  428.         addq.b    #1,d0            ;advance pointer
  429.         move.b    21(a0,d0.w),d1        ;get command
  430.         bmi.s    synth_cmd        ;negative = command
  431.         move.b    d1,trk_synvol(a5)    ;set synthvol
  432.         move.b    d1,ac_vol+1(a3)        ;change it!!
  433.         bra.w    synth_endvol        ;end of volume executing
  434. synth_cmd:    and.w    #$000f,d1
  435.         add.b    d1,d1
  436.         move.w    synth_vtbl(pc,d1.w),d1
  437.         jmp    syv(pc,d1.w)
  438. synth_vtbl:    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  439.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  440.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  441.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  442.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  443. syv:
  444. syv_fe:        move.b    22(a0,d0.w),d0        ;JMP
  445.         bra.s    synth_getvolcmd
  446. syv_f0:        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  447.         bra.s    synth_inccnt
  448. syv_f1:        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  449.         addq.b    #1,d0
  450.         bra.s    synth_endvol
  451. syv_f3:        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  452.         bra.s    synth_inccnt
  453. syv_f2:        move.b    22(a0,d0.w),d1
  454.         neg.b    d1
  455.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  456.         bra.s    synth_inccnt
  457. syv_fa:        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  458.         clr.b    trk_wfwait(a5)
  459.         bra.s    synth_inccnt
  460. syv_f4:        move.b    22(a0,d0.w),d1
  461.         bsr.s    synth_getwf
  462.         clr.l    trk_envrestart(a5)
  463. syv_f4end    move.l    a1,trk_envptr(a5)
  464.         clr.b    trk_envcount(a5)
  465.         bra.w    synth_inccnt
  466. syv_f5:        move.b    22(a0,d0.w),d1
  467.         bsr.s    synth_getwf
  468.         move.l    a1,trk_envrestart(a5)
  469.         bra.s    syv_f4end
  470. syv_f6        clr.l    trk_envptr(a5)
  471.         bra.w    synth_getvolcmd
  472. synth_getwf    ext.w    d1    ;d1 = wform number, returns ptr in a1
  473.         add.w    d1,d1    ;create index
  474.         add.w    d1,d1
  475.         lea    278(a0),a1
  476.         adda.w    d1,a1
  477.         movea.l    (a1),a1        ;get wform address
  478.         addq.l    #2,a1        ;skip length
  479.         rts
  480. syv_ff:        subq.b    #1,d0
  481. synth_endvol:    move.w    d0,trk_volcmd(a5)
  482. synth_wftbl:    move.b    trk_synvol(a5),trk_prevvol(a5)
  483.         adda.w    #158,a0
  484.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  485.         bgt.w    synth_arpeggio        ;not yet...
  486.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  487.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  488.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  489.         beq.s    synth_tstwfwai        ;0 = no change
  490. wytanwet:    add.w    trk_perchg(a5),d1    ;add value to current change
  491.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  492.         add.w    trk_prevper(a5),d1    ;add initial period to it
  493.         cmp.w    #113,d1            ;overflow??
  494.         bge.s    synth_pern2h
  495.         moveq    #113,d1
  496. synth_pern2h:    move.w    d1,ac_per(a3)        ;push the changed period
  497. synth_tstwfwai:    tst.b    trk_wfwait(a5)        ;WAI ??
  498.         beq.s    synth_getwfcmd        ;not waiting...
  499.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  500.         beq.s    synth_getwfcmd        ;waiting finished
  501.         bra.w    synth_arpeggio        ;still sleep...
  502. synth_incwfc:    addq.b    #1,d0
  503. synth_getwfcmd:    addq.b    #1,d0            ;advance position counter
  504.         move.b    -9(a0,d0.w),d1        ;get command
  505.         bmi.s    synth_wfcmd        ;negative = command
  506.         ext.w    d1
  507.         add.w    d1,d1
  508.         add.w    d1,d1
  509.         movea.l    120(a0,d1.w),a1
  510.         move.w    (a1)+,ac_len(a3)    ;push waveform length
  511.         move.l    a1,(a3)         ;and the new pointer (0 = ac_ptr)
  512.         bra.w    synth_wfend        ;no new commands now...
  513. synth_wfcmd:    and.w    #$000f,d1        ;get the right nibble
  514.         add.b    d1,d1            ;* 2
  515.         move.w    synth_wfctbl(pc,d1.w),d1
  516.         jmp    syw(pc,d1.w)        ;jump to command
  517. synth_wfctbl:    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  518.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  519.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  520.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  521. syw:
  522. syw_f7:        move.b    -8(a0,d0.w),d1
  523.         ext.w    d1
  524.         add.w    d1,d1
  525.         add.w    d1,d1
  526.         movea.l    120(a0,d1.w),a1
  527.         addq.l    #2,a1
  528.         move.l    a1,trk_synvibwf(a5)
  529.         bra.s    synth_incwfc
  530. syw_fe:        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  531.         bra.s    synth_getwfcmd
  532. syw_fc:        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  533.         move.w    d0,trk_arpgoffs(a5)
  534. synth_findare:    addq.b    #1,d0
  535.         tst.b    -9(a0,d0.w)
  536.         bpl.s    synth_findare
  537.         bra.s    synth_getwfcmd
  538. syw_f0:        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  539.         bra    synth_incwfc
  540. syw_f1:        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  541.         addq.b    #1,d0
  542.         bra.s    synth_wfend
  543. syw_f4:        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  544.         bra.w    synth_incwfc
  545. syw_f5:        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  546.         addq.b    #1,trk_synthvibspd+1(a5)
  547.         bra.w    synth_incwfc
  548. syw_f2:        moveq    #0,d1            ;set slide down
  549.         move.b    -8(a0,d0.w),d1
  550. synth_setsld:    move.w    d1,trk_wfchgspd(a5)
  551.         bra.w    synth_incwfc
  552. syw_f3:        move.b    -8(a0,d0.w),d1        ;set slide up
  553.         neg.b    d1
  554.         ext.w    d1
  555.         bra.s    synth_setsld
  556. syw_f6:        clr.w    trk_perchg(a5)        ;reset period
  557.         move.w    trk_prevper(a5),ac_per(a3)
  558.         bra.w    synth_getwfcmd
  559. syw_fa:        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  560.         clr.b    trk_volwait(a5)
  561.         bra.w    synth_incwfc
  562. syw_ff:        subq.b    #1,d0        ;pointer = END - 1
  563. synth_wfend:    move.w    d0,trk_wfcmd(a5)
  564. synth_arpeggio:    move.w    trk_arpgoffs(a5),d0
  565.         beq.s    synth_vibrato
  566.         moveq    #0,d1
  567.         move.b    -8(a0,d0.w),d1
  568.         add.b    trk_prevnote2(a5),d1
  569.         movea.l    trk_periodtbl(a5),a1    ;get period table
  570.         add.w    d1,d1
  571.         move.w    0(a1,d1.w),d1
  572.         add.w    trk_perchg(a5),d1
  573.         move.w    d1,trk_prevper(a5)
  574.         move.w    d1,ac_per(a3)
  575.         addq.b    #1,d0
  576.         tst.b    -8(a0,d0.w)
  577.         bpl.s    synth_noarpres
  578.         move.w    trk_arpsoffs(a5),d0
  579. synth_noarpres:    move.w    d0,trk_arpgoffs(a5)
  580. synth_vibrato:    move.w    trk_synvibdep(a5),d1    ;get vibrato depth
  581.         beq.s    synth_rts        ;0 => no vibrato
  582.         move.w    trk_synviboffs(a5),d0    ;get offset
  583.         lsr.w    #4,d0            ;/ 16
  584.         and.w    #$1f,d0            ;sinetable offset (0-31)
  585.         movea.l trk_synvibwf(a5),a0
  586.         move.b    0(a0,d0.w),d0       ;get a byte
  587.         ext.w    d0            ;to word
  588.         muls    d1,d0            ;amplify (* depth)
  589.         asr.w    #8,d0            ;and divide by 64
  590.         move.w    trk_prevper(a5),d1    ;get the old period
  591.         add.w    d0,d1            ;add vibrato...
  592.         add.w    trk_perchg(a5),d1    ;and pitch change...
  593.         move.w    d1,ac_per(a3)        ;change.
  594.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  595.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  596. synth_rts:    move.l    (sp)+,a3
  597.         rts
  598.     ENDC
  599. sinetable:    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  600.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  601.         dc.b    -106,-90,-71,-49,-25,0
  602.  
  603. _Wait1line:    move.l    d0,-(sp)    ;d1 = vsync counters to wait - 1
  604. wl0:        move.b    $dff007,d0
  605. wl1:        cmp.b    $dff007,d0
  606.         beq.s    wl1
  607.         dbf    d1,wl0
  608.         move.l    (sp)+,d0
  609.         rts
  610. pushnewvals:    movea.l    (a1)+,a5
  611.         lsr.b    #1,d0
  612.         bcc.s    rpnewv
  613.         move.l    trk_sampleptr(a5),d1
  614.         beq.s    rpnewv
  615.         movea.l    trk_audioaddr(a5),a0
  616.         move.l    d1,(a0)+        ;0 = ac_ptr
  617.         move.w    trk_samplelen(a5),(a0)    ;4 = ac_len
  618. rpnewv:        rts
  619. _StartDMA:        ;This small routine turns on audio DMA
  620.         move.w    dmaonmsk(pc),d0    ;dmaonmsk contains the mask of
  621.     IFNE MIDI
  622.         beq.s    sdma_nodmaon    ;the channels that must be turned on
  623.     ENDC
  624.     IFEQ MIDI
  625.         beq.s    rpnewv
  626.     ENDC
  627.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  628.         moveq    #80,d1
  629.     IFNE    SYNTH
  630.         add.w    d1,d1    ;sometimes double wait time is required
  631.     ENDC
  632.         bsr.s    _Wait1line
  633.         move.w    d0,$dff096    ;do that!!!
  634.         moveq    #79,d1
  635.         bsr.s    _Wait1line
  636.         lea    trackdataptrs(pc),a1
  637.         bsr.s    pushnewvals
  638.         bsr.s    pushnewvals
  639.         bsr.s    pushnewvals
  640.     IFNE MIDI
  641.         bsr.s    pushnewvals
  642. sdma_nodmaon    lea    bytesinnotebuff(pc),a0
  643.         move.w    (a0)+,d0
  644.         beq.s    rpnewv
  645.         bra.w    _AddMIDIData
  646.     ENDC
  647.     IFEQ MIDI
  648.         bra.s    pushnewvals
  649.     ENDC
  650.  
  651.     IFNE MIDI
  652. prevmidipbend:    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  653.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  654.     ENDC
  655. ; TRACK-data structures (see definitions at the end of this file)
  656. t03d:        ds.b    20
  657.         dc.l    $dff0a0
  658.         ds.b    64+20
  659.         dc.l    $dff0b0
  660.         ds.b    64+20
  661.         dc.l    $dff0c0
  662.         ds.b    64+20
  663.         dc.l    $dff0d0
  664.         ds.b    64
  665. t415d:        ds.b    4*T415SZ
  666. t815d:        ds.b    8*T415SZ    ;8 bytes * 12 tracks = 96 bytes
  667. trackdataptrs:    dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  668.         dc.l    t415d,t415d+T415SZ,t415d+2*T415SZ,t415d+3*T415SZ
  669.         dc.l    t815d,t815d+T415SZ,t815d+2*T415SZ,t815d+3*T415SZ
  670.         dc.l    t815d+4*T415SZ,t815d+5*T415SZ,t815d+6*T415SZ
  671.         dc.l    t815d+7*T415SZ
  672. numtracks:    dc.w    0
  673. numlines:    dc.w    0
  674. nextblock:    dc.b    0,0
  675.  
  676.  
  677. _IntHandler:    movem.l    d2-d7/a2-a5,-(sp)
  678.         movea.l    _module(pc),a6    ;a6 = pointer of MMD0
  679.         move.l    a6,d0
  680.         beq.w    plr_exit
  681.         tst.w    mmd_pstate(a6)
  682.         beq.w    plr_exit
  683.     IFNE    MIDI
  684.         clr.l    dmaonmsk
  685.     ENDC
  686.     IFEQ    MIDI
  687.         clr.w    dmaonmsk
  688.     ENDC
  689.         movea.l    mmd_songinfo(a6),a4
  690.         move.l    a4,d0
  691.         beq.w    plr_exit
  692.         moveq    #0,d3
  693.         move.b    mmd_counter(a6),d3
  694.         addq.b    #1,d3
  695.         cmp.b    msng_tempo2(a4),d3
  696.         bge.s    plr_pnewnote    ;play new note
  697.         move.b    d3,mmd_counter(a6)
  698.         bne.w    nonewnote    ;do just fx
  699. ; --- new note!! first get address of current block
  700. plr_pnewnote:    clr.b    mmd_counter(a6)
  701. ; --- now start to play it
  702.         move.w    mmd_pblock(a6),d0
  703.         movea.l    mmd_blockarr(a6),a0
  704.         add.w    d0,d0
  705.         add.w    d0,d0
  706.         movea.l    0(a0,d0.w),a2    ;block...
  707.         move.b    (a2)+,numtracks+1
  708.         move.b    (a2)+,numlines+1
  709.         move.w    mmd_pline(a6),d0
  710.         move.w    d0,d1
  711.         add.w    d0,d0    ;d0 * 2
  712.         add.w    d1,d0    ;+ d0 = d0 * 3
  713.         mulu    numtracks(pc),d0
  714.         adda.w    d0,a2        ;a2 => pointer of curr. note
  715.         moveq    #0,d7        ;number of track
  716.         pea    trackdataptrs(pc)
  717. plr_loop0:    moveq    #0,d5
  718.         move.l    (sp),a1
  719.         movea.l    (a1)+,a5    ;get address of this track's struct
  720.         move.l    a1,(sp)
  721. ; ---------------- get the note numbers
  722.         move.b    (a2)+,d5    ;get the number of this note
  723.         move.b    (a2)+,d6    ;and the 4 numbers containing fx
  724.         move.b    (a2)+,trk_cmdqual(a5)    ;get & save the fx numbers
  725. ; ---------------- clear some instrument # flags
  726.         moveq    #0,d4        ;d4 is a flag: if set, instr. is
  727.         moveq    #0,d3        ;in range G-V. If clr, it's 1-F.
  728. ; ---------------- and set them, if needed
  729.         bclr    #7,d5        ;d3 is also a flag. If it's set,
  730.         sne    d4        ;the instr. is in range 10 - 1V
  731.         bclr    #6,d5
  732.         sne    d3
  733. ; ---------------- check if there's an instrument number
  734.         move.b    d6,d0
  735.         and.w    #$f0,d0        ;d0 now contains only the # of instr
  736.         bne.s    instnum        ;instrument number is not 0
  737.         tst.b    d4        ;maybe it's G (instr. #0, d4 set)
  738.         bne.s    instnum        ;yes, it really was G!!
  739.         tst.b    d3
  740.         beq.s    noinstnum    ;it wasn't 10 - 1V either..
  741. ; ---------------- if there was, get it
  742. instnum:    lsr.b    #4,d0        ;shift it right to get number 0-F
  743.         tst.b    d4
  744.         beq.s    nogtov2
  745.         add.w    #16,d0        ;if G-V, add 16 to the number
  746. nogtov2:    tst.b    d3
  747.         beq.s    no10to1v
  748.         add.w    #32,d0
  749. ; ---------------- finally, save the number
  750. no10to1v:    subq.b    #1,d0
  751.         move.b    d0,trk_previnstr(a5) ;remember instr. number!
  752.     IFNE    HOLD
  753. ; ---------------- remember hold/decay values
  754.         lea    holdvals(pc),a0
  755.         move.b    0(a0,d0.w),trk_inithold(a5)
  756.         move.b    63(a0,d0.w),trk_initdecay(a5)
  757.     ENDC
  758. ; ---------------- get the pointer of data's of this sample in Song-struct
  759.         asl.w    #3,d0
  760.         lea    0(a4,d0.w),a3    ;a3 contains now address of it
  761.         move.l    a3,trk_previnstra(a5)
  762.         moveq    #0,d0
  763. ; ---------------- get volume and make it relative (1 - 100 %)
  764.     IFNE    RELVOL
  765.         move.b    inst_svol(a3),d0
  766.         mulu    trk_trackvol(a5),d0
  767.         lsr.w    #8,d0
  768.         move.b    d0,trk_prevvol(a5) ;vol of this instr
  769.     ENDC
  770.     IFEQ    RELVOL
  771.         move.b    inst_svol(a3),trk_prevvol(a5)
  772.     ENDC
  773. ; ---------------- remember transpose
  774.         move.b    inst_strans(a3),trk_stransp(a5)
  775. ; ---------------- check the commands
  776. noinstnum    and.b    #$0f,d6        ;now check only the effect part
  777.         move.b    d6,trk_cmd(a5)    ;save the effect number
  778.         beq.w    plr_nocmd    ;no effect
  779.         move.b    d6,d0
  780.         move.b    trk_cmdqual(a5),d6    ;get qualifier...
  781. ; ---------------- there was a command (effect), but which one??
  782.         cmp.b    #$0f,d0        ;yes effect...is it Tempo???
  783.         bne.w    not0f        ;not Tempo
  784. ; ---------------- it was tempo (F)
  785.         tst.b    d6        ;test effect qual..
  786.         beq.s    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  787.         cmp.b    #$f0,d6        ;..is zero, go to next block
  788.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  789. ; ---------------- just an ordinary "change tempo"-request
  790.     IFNE    CIAB
  791.         moveq    #0,d0        ;will happen!!!
  792.         move.b    d6,d0
  793.         bsr    _SetTempo    ;change The Tempo
  794.         move.b    d6,msng_deftempo(a4)
  795.     ENDC
  796.         bra.w    plr_nocmd
  797. ; ---------------- it was FFx
  798. fx0fspecial:    cmp.b    #$f2,d6
  799.         bne.s    isfxfe
  800. ; ---------------- it was FF2, nothing to do now
  801.         move.b    d5,(a5)
  802.         moveq    #0,d5
  803.         bra.w    plr_nocmd
  804. isfxfe:        cmp.b    #$fe,d6
  805.         bne.s    notcmdfe
  806. ; ---------------- it was FFE, stop playing
  807.         clr.w    mmd_pstate(a6)
  808.     IFNE    CIAB
  809.         movea.l    craddr(pc),a0
  810.         bclr    #0,(a0)
  811.     ENDC
  812.         bsr.w    SoundOff
  813.         addq.l    #4,sp
  814.         bra.w    plr_exit
  815. notcmdfe:    cmp.b    #$fd,d6 ;change period
  816.         bne.s    isfxff
  817. ; ---------------- FFD, change the period, don't replay the note
  818.     IFNE    CHECK
  819.         cmp.w    #4,d7 ;no tracks 4 - 15
  820.         bge.w    plr_nocmd
  821.     ENDC
  822.         movea.l    trk_periodtbl(a5),a0    ;period table
  823.         subq.b    #1,d5    ;sub 1 to make "real" note number
  824.         bmi.w    plr_endloop0    ;under zero, do nothing
  825.         add.b    d5,d5
  826.         move.w    0(a0,d5.w),d0 ;get the period
  827.         movea.l    trk_audioaddr(a5),a0
  828.         move.w    d0,ac_per(a0) ;push the period
  829.         moveq    #0,d5 ;and clear it so that it won't be replayed
  830.         bra.w    plr_nocmd    ;done!!
  831. isfxff:        cmp.b    #$ff,d6        ;note off??
  832.         bne.w    plr_nocmd
  833.         move.w    d7,d0
  834.         bsr.w    _ChannelOff
  835.         bra.w    plr_nocmd
  836. ; ---------------- F00, called Pattern Break in ST
  837. fx0fchgblck:    addq.b    #1,nextblock    ;next block... (F00)
  838.         bra.w    plr_nocmd
  839. ; ---------------- was not Fxx, then it's something else!!
  840. not0f:        cmp.b    #$0e,d0
  841.         bne.s    not0e
  842.         move.b    d6,trk_wfcmd+1(a5) ;set waveform command position ptr
  843.         bra.w    plr_nocmd
  844. not0e:        cmp.b    #$0c,d0        ;new volume???
  845.         bne.s    not0c        ;NO
  846. ; ---------------- change volume
  847.         move.b    d6,d0
  848.         bpl.s    plr_nosetdefvol
  849.         and.b    #$7F,d0
  850.     IFNE    CHECK
  851.         cmp.b    #64,d0
  852.         bgt.s    go_nocmd
  853.     ENDC
  854.         moveq    #0,d1
  855.         move.b    trk_previnstr(a5),d1
  856.         asl.w    #3,d1
  857.         move.b    d0,inst_svol(a4,d1.w)    ;set new svol
  858.         bra.s    plr_setvol
  859. plr_nosetdefvol    btst    #4,msng_flags(a4)    ;look at flags
  860.         bne.s    volhex
  861.         lsr.b    #4,d0        ;get number from left
  862.         mulu    #10,d0        ;number of tens
  863.         move.b    d6,d1        ;get again
  864.         and.b    #$0f,d1        ;this time don't get tens
  865.         add.b    d1,d0        ;add them
  866. volhex:
  867.     IFNE    CHECK
  868.         cmp.b    #64,d0
  869.         bhi.s    go_nocmd
  870.     ENDC
  871. plr_setvol
  872.     IFNE    RELVOL
  873.         mulu    trk_trackvol(a5),d0
  874.         lsr.w    #8,d0
  875.     ENDC
  876.         move.b    d0,trk_prevvol(a5)
  877. go_nocmd    bra.w    plr_nocmd
  878. ; ---------------- tempo2 change??
  879. not0c:        cmp.b    #$09,d0
  880.         bne.s    not09
  881.     IFNE    CHECK
  882.         and.b    #$1F,d6
  883.         bne.s    fx9chk
  884.         moveq    #$20,d6
  885.     ENDC
  886. fx9chk:        move.b    d6,msng_tempo2(a4)
  887.         bra.s    plr_nocmd
  888. ; ---------------- note off time set??
  889.     IFNE    HOLD
  890. not09:        cmp.b    #$08,d0
  891.         bne.s    not08
  892.         move.b    d6,d0
  893.         lsr.b    #4,d6        ;extract left  nibble
  894.         and.b    #$0f,d0        ; "   "  right  "  "
  895.         move.b    d6,trk_initdecay(a5)    ;left = decay
  896.         move.b    d0,trk_inithold(a5)    ;right = hold
  897.         bra.s    plr_nocmd
  898.     ENDC
  899.     IFEQ    HOLD
  900. not09
  901.     ENDC
  902. ; ---------------- cmd Bxx, "position jump", like Goto, yäk!!
  903. not08:        cmp.b    #$0b,d0
  904.         bne.s    not0b
  905.         move.w    d6,d0
  906.         and.w    #$00ff,d0
  907.     IFNE    CHECK
  908.         cmp.w    msng_songlen(a4),d0    ;test the song length
  909.         bhi.s    plr_nocmd
  910.     ENDC
  911.         move.w    d0,mmd_pseqnum(a6)
  912.         st    nextblock    ; = -1
  913.         bra.s    plr_nocmd
  914. ; ---------------- try portamento (3)
  915. not0b:        cmp.b    #$03,d0
  916.         bne.s    plr_nocmd
  917.         subq.b    #1,d5        ;subtract note number
  918.         bpl.s    plr_fx3note    ;there's a note...
  919.         tst.b    d6        ;qual??
  920.         beq.s    plr_endloop0    ;0 -> do nothing
  921.         bra.s    plr_setfx3spd    ;not 0 -> set new speed
  922. plr_fx3note:
  923.     IFNE    CHECK
  924.         cmp.w    #4,d7
  925.         bge.s    plr_endloop0    ;hey, what are you trying to do??
  926.     ENDC
  927.         movea.l    trk_periodtbl(a5),a0
  928.         add.b    msng_playtransp(a4),d5    ;play transpose
  929.         add.b    trk_stransp(a5),d5 ;and instrument transpose
  930.         bmi.s    plr_endloop0    ;again.. too low
  931.         add.w    d5,d5
  932.         move.w    0(a0,d5.w),trk_porttrgper(a5) ;period of this note is the target
  933. plr_setfx3spd:    move.b    d6,trk_prevportspd(a5)    ;remember size
  934.         moveq    #0,d5    ;don't play this one
  935. ; ---------------- everything is checked now: play or not to play??
  936. plr_nocmd:    tst.b    d5    ;Now we'll check if we have to play a note
  937.         beq.s    plr_endloop0    ;no.
  938. ; ---------------- we decided to play
  939.         move.b    d5,(a5)
  940.         move.w    d7,d0
  941.         move.w    d5,d1
  942.         moveq    #0,d2
  943.         move.b    trk_prevvol(a5),d2    ;get volume
  944.         moveq    #0,d3
  945.         move.b    trk_previnstr(a5),d3    ;instr #
  946.         movea.l    trk_previnstra(a5),a3    ;instr data address
  947. ; ---------------- does this instrument have holding??
  948.     IFNE    HOLD
  949.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  950.         bne.s    plr_holdok    ;not 0 -> OK
  951.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  952.     ENDC
  953. ; ---------------- and finally:
  954. plr_holdok:    bsr    _PlayNote    ;play it!!!!!!!!!!!
  955. ; ---------------- end of loop: handle next track, or quit
  956. plr_endloop0:    addq.b    #1,d7
  957.         cmp.w    numtracks(pc),d7
  958.         blt.w    plr_loop0
  959.         addq.l    #4,sp        ;trackdataptrs
  960.  
  961. ; and advance song pointers
  962.         lea    nextblock(pc),a2
  963.         move.w    mmd_pline(a6),d1    ;pline
  964.         addq.w    #1,d1            ;advance line
  965.         cmp.w    numlines(pc),d1        ;advance block?
  966.         bgt.s    plr_chgblock        ;yes
  967.         tst.b    (a2)            ;command F00 ??
  968.         beq.s    plr_nochgblock        ;no, don't change block
  969. plr_chgblock:    moveq    #0,d1            ;clear the line number
  970.         tst.w    mmd_pstate(a6)        ;play block or play song
  971.         bpl.s    plr_nonewseq        ;play block only...
  972.         move.w    mmd_pseqnum(a6),d0    ;get play sequence number
  973.         tst.b    (a2)
  974.         bmi.s    plr_noadvseq    ;Bxx sets nextblock to 0xff (= neg)
  975.         addq.w    #1,d0            ;advance sequence number
  976. plr_noadvseq:    cmp.w    msng_songlen(a4),d0    ;is this the highest seq number??
  977.         blt.s    plr_notagain        ;no.
  978.         moveq    #0,d0            ;yes: play song again
  979.         moveq    #0,d1            ;...forever
  980. plr_notagain:    move.b    d0,mmd_pseqnum+1(a6)    ;remember new playseq-#
  981.         lea    msng_playseq(a4),a0    ;offset of sequence table
  982.         move.b    0(a0,d0.w),d0        ;get number of the block
  983.     IFNE    CHECK
  984.         cmp.b    msng_numblocks+1(a4),d0    ;beyond last block??
  985.         blt.s    plr_nolstblk        ;no..
  986.         moveq    #0,d0            ;play block 0
  987.     ENDC
  988. plr_nolstblk:    move.b    d0,mmd_pblock+1(a6)    ;store pblock
  989. plr_nonewseq:    clr.b    (a2)            ;clear this if F00 set it
  990. plr_nochgblock:    move.w    d1,mmd_pline(a6)    ;set new pline
  991.  
  992.     IFNE    HOLD
  993.         movea.l    mmd_blockarr(a6),a0
  994.         move.w    mmd_pblock(a6),d0
  995.         add.w    d0,d0
  996.         add.w    d0,d0
  997.         movea.l    0(a0,d0.w),a2
  998.         move.b    (a2),d7            ;# of tracks
  999.         move.w    mmd_pline(a6),d0    ;play line
  1000.         move.w    d0,d1
  1001.         add.w    d0,d0    ;d0 * 2
  1002.         add.w    d1,d0    ;+ d0 = d0 * 3
  1003.         mulu    d7,d0
  1004.         lea    2(a2,d0.w),a2
  1005.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  1006.         lea    trackdataptrs(pc),a0
  1007.         subq.b    #1,d7
  1008. plr_chkhold:    movea.l    (a0)+,a1        ;track data
  1009.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1010.         bmi.s    plr_holdend        ;no.
  1011.         move.b    (a2),d1            ;get the 1st byte..
  1012.         bne.s    plr_hold1
  1013.         move.b    1(a2),d1
  1014.         and.b    #$f0,d1
  1015.         beq.s    plr_holdend        ;don't hold
  1016.         bra.s    plr_hold2
  1017. plr_hold1:    and.b    #$3f,d1            ;note??
  1018.         beq.s    plr_hold2        ;no, cont hold..
  1019.         move.b    1(a2),d1
  1020.         and.b    #$0f,d1            ;get cmd
  1021.         subq.b    #3,d1            ;is there command 3 (slide)
  1022.         bne.s    plr_holdend        ;no -> end holding
  1023. plr_hold2:    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1024. plr_holdend:    addq.l    #3,a2        ;next note
  1025.         dbf    d7,plr_chkhold
  1026.     ENDC
  1027.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  1028.         bne.w    plr_endfx        ;yes, no effects this time...
  1029.         moveq    #0,d3            ;counter = 0
  1030. nonewnote:
  1031. ;    *********************** This code produces the effects **
  1032.         moveq    #0,d7    ;clear track count
  1033.         moveq    #0,d6
  1034.         lea    trackdataptrs(pc),a2
  1035. plr_loop1:    movea.l    (a2)+,a5
  1036.         moveq    #0,d5
  1037.         moveq    #0,d4
  1038.         move.b    trk_cmd(a5),d6    ;get the fx number
  1039.         move.b    trk_cmdqual(a5),d4    ;and the last 2 #'s
  1040.     IFNE    MIDI
  1041.         tst.b    trk_prevmidin(a5)    ;first: is it MIDI??
  1042.         bne.w    midicmds
  1043.     ENDC
  1044.         cmp.w    #4,d7
  1045.         bge.w    endl    ;no non-MIDI effects in tracks 4 - 15
  1046.     IFNE    HOLD
  1047.         tst.b    trk_noteoffcnt(a5)
  1048.         bmi.s    plr_nowaitoff
  1049.         subq.b    #1,trk_noteoffcnt(a5)
  1050.         bpl.s    plr_nowaitoff
  1051.         IFNE    SYNTH
  1052.         tst.b    trk_synthtype(a5)    ;synth/hybrid??
  1053.         beq.s    plr_nosyndec
  1054.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  1055.         clr.b    trk_volwait(a5)    ;abort WAI
  1056.         move.l    trk_synthptr(a5),d0
  1057.         bra.s    plr_gosynth
  1058.         ENDC
  1059. plr_nosyndec:    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  1060.         bne.s    plr_nowaitoff    ;if > 0, don't stop sound
  1061.         bset    d7,d5
  1062.         move.w    d5,$dff096    ;shut DMA...
  1063.         moveq    #0,d5
  1064.     ENDC
  1065. plr_nowaitoff:
  1066.     IFNE    SYNTH
  1067.         move.l    trk_synthptr(a5),d0
  1068.         beq.s    plr_nosynth
  1069. plr_gosynth:    move.l    d0,a0
  1070.         bsr.w    synth_start
  1071.     ENDC
  1072. plr_nosynth:
  1073.     IFNE    HOLD
  1074.         move.b    trk_fadespd(a5),d0    ;fade??
  1075.         beq.s    plr_nofade    ;no.
  1076.         sub.b    d0,trk_prevvol(a5)
  1077.         bpl.s    plr_nofade2low
  1078.         clr.b    trk_prevvol(a5)
  1079.         clr.b    trk_fadespd(a5)        ;fade no more
  1080. plr_nofade2low:
  1081.     ENDC
  1082. plr_nofade:    movea.l    trk_audioaddr(a5),a1
  1083.         add.b    d6,d6    ;* 2
  1084.         move.w    fx_table(pc,d6.w),d0
  1085.         jmp    fxs(pc,d0.w)
  1086. fx_table:    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1087.         dc.w    fx_05-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1088.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_xx-fxs,fx_0d-fxs,fx_xx-fxs
  1089.         dc.w    fx_0f-fxs
  1090. fxs:
  1091. ;    **************************************** Effect 01 ******
  1092. fx_01:        sub.w    d4,trk_prevper(a5)    ;slide up
  1093.         move.w    trk_prevper(a5),d5
  1094.         cmp.w    #113,d5        ;too high?
  1095.         bge.s    fx_01_pushper
  1096.         move.w    #113,d5        ;too high
  1097.         move.w    d5,trk_prevper(a5)
  1098. fx_01_pushper    move.w    d5,ac_per(a1)
  1099.         bra.w    fx_xx
  1100. ;    **************************************** Effect 02 ******
  1101. fx_02:        add.w    d4,trk_prevper(a5)    ;slide down
  1102.         move.w    trk_prevper(a5),d5
  1103.         bra.s    fx_01_pushper
  1104. ;    **************************************** Effect 00 ******
  1105. fx_00:        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio
  1106.         beq.w    fx_xx
  1107.         move.l    d3,d0
  1108.         divu    #3,d0
  1109.         swap    d0
  1110.         tst.w    d0
  1111.         bne.s    fx_arp12
  1112.         and.b    #$0f,d4
  1113.         add.b    (a5),d4
  1114.         bra.s    fx_doarp
  1115. fx_arp12:    subq.b    #1,d0
  1116.         bne.s    fx_arp2
  1117.         lsr.b    #4,d4
  1118.         add.b    (a5),d4
  1119.         bra.s    fx_doarp
  1120. fx_arp2:    move.b    (a5),d4
  1121. fx_doarp:    subq.b    #1,d4        ;-1 to make it 0 - 127
  1122.         add.b    msng_playtransp(a4),d4    ;add play transpose
  1123.         add.b    trk_stransp(a5),d4    ;add instrument transpose
  1124.         add.b    d4,d4        ;shift to make index for UWORD
  1125.         movea.l    trk_periodtbl(a5),a0
  1126.         move.w    0(a0,d4.w),ac_per(a1)
  1127.         bra.w    fx_xx
  1128. ;    **************************************** Effect 0D/0A ***
  1129. fx_0a:
  1130. fx_0d:        move.b    d4,d1
  1131.         move.b    trk_prevvol(a5),d0    ;move previous vol to d0
  1132.         and.b    #$f0,d1
  1133.         bne.s    crescendo
  1134.         sub.b    d4,d0    ;sub from prev. vol
  1135.         bpl.s    fx_0d_pushvol
  1136.         moveq    #0,d0    ;volumes under zero not accepted
  1137.         bra.s    fx_0d_pushvol
  1138. crescendo:    lsr.b    #4,d1
  1139.         add.b    d1,d0
  1140.         cmp.b    #64,d0
  1141.         ble.s    fx_0d_pushvol
  1142.         moveq    #64,d0
  1143. fx_0d_pushvol    move.b    d0,trk_prevvol(a5)
  1144.         move.b    d0,ac_vol+1(a1)
  1145.         bra.w    endl
  1146. ;    **************************************** Effect 05 ******
  1147. fx_05:        move.w    trk_prevper(a5),d5 ;this is very simple: get the old period
  1148.         cmp.b    #3,d3        ;and..
  1149.         bge.w    fx_05b        ;if counter < 3
  1150.         sub.w    d4,d5    ;subtract effect qualifier
  1151. fx_05b        move.w    d5,ac_per(a1)
  1152.         bra.w    fx_xx
  1153. ;    **************************************** Effect 03 ******
  1154. fx_03:        move.w    trk_porttrgper(a5),d0    ;d0 = target period
  1155.         beq.w    fx_xx        ;no target period specified
  1156.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  1157.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  1158.         cmp.w    d0,d1
  1159.         bhi.s    subper    ;curr. period > target period
  1160.         add.w    d4,d1    ;add the period
  1161.         cmp.w    d0,d1
  1162.         bge.s    targreached
  1163.         bra.s    targnreach
  1164. subper:        sub.w    d4,d1    ;subtract
  1165.         cmp.w    d0,d1    ;compare current period to target period
  1166.         bgt.s    targnreach
  1167. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  1168.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  1169. targnreach:    move.w    d1,trk_prevper(a5)
  1170.         move.w    d1,ac_per(a1)
  1171.         bra.w    fx_xx
  1172. ;    **************************************** Effect 04 ******
  1173. fx_04:        tst.b    d4
  1174.         beq.s    nonvib
  1175.         move.b    d4,trk_vibrspdsz(a5)
  1176. nonvib:        move.b    trk_vibroffs(a5),d0
  1177.         lsr.b    #2,d0
  1178.         and.w    #$1f,d0
  1179.         moveq    #0,d1
  1180.         lea    sinetable(pc),a0
  1181.         move.b    0(a0,d0.w),d5
  1182.         ext.w    d5
  1183.         move.b    trk_vibrspdsz(a5),d0
  1184.         and.w    #$000f,d0
  1185.         muls    d0,d5
  1186.         asr.w    #5,d5
  1187.         add.w    trk_prevper(a5),d5
  1188.         move.b    trk_vibrspdsz(a5),d0
  1189.         lsr.b    #3,d0
  1190.         and.b    #$3e,d0
  1191.         add.b    d0,trk_vibroffs(a5)
  1192.         move.w    d5,ac_per(a1)
  1193.         bra.s    fx_xx
  1194. ;    **************************************** Effect 0F ******
  1195. fx_0f:        cmp.b    #$f1,d4
  1196.         bne.s    no0ff1
  1197.         cmp.b    #3,d3
  1198.         bne.w    fx_xx
  1199.         bra.s    playfxnote
  1200. no0ff1:        cmp.b    #$f2,d4
  1201.         bne.s    no0ff2
  1202.         cmp.b    #3,d3
  1203.         bne.w    fx_xx
  1204.         bra.s    playfxnote
  1205. no0ff2:        cmp.b    #$f3,d4
  1206.         bne.s    no0ff3
  1207.         move.b    d3,d0
  1208.         and.b    #2+4,d0        ;is 2 or 4
  1209.         beq.s    fx_xx
  1210. playfxnote:    move.w    d7,d0        ;track # to d0...
  1211.         moveq    #0,d1
  1212.         move.b    (a5),d1        ;get note # of previous note
  1213.         beq.s    fx_xx
  1214.         moveq    #0,d2
  1215.         move.b    trk_prevvol(a5),d2    ;get previous volume
  1216.         move.l    d3,-(sp)
  1217.         moveq    #0,d3
  1218.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  1219.         movea.l    trk_previnstra(a5),a3
  1220.         bsr    _PlayNote
  1221.         move.l    (sp)+,d3
  1222.         bra.s    fx_xx
  1223. no0ff3:        cmp.b    #$f8,d4        ;f8 = filter off
  1224.         beq.s    plr_filteroff
  1225.         cmp.b    #$f9,d4        ;f9 = filter on
  1226.         bne.s    fx_xx
  1227.         bclr    #1,$bfe001
  1228.         bra.s    fx_xx
  1229. plr_filteroff:    bset    #1,$bfe001
  1230. ;    *********************************************************
  1231. fx_xx:        move.b    trk_prevvol(a5),ac_vol+1(a1)
  1232. endl:        addq.b    #1,d7    ;increment channel number
  1233.         cmp.w    numtracks(pc),d7    ;all channels done???
  1234.         blt.w    plr_loop1    ;not yet!!!
  1235. plr_endfx    bsr    _StartDMA    ;turn on DMA
  1236. plr_exit    movem.l    (sp)+,d2-d7/a2-a5
  1237.     IFNE    VBLANK
  1238.         moveq    #0,d0
  1239.     ENDC
  1240.         rts
  1241.  
  1242. _SetTempo:
  1243.     IFNE    CIAB
  1244.         cmp.b    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  1245.         bhi.s    calctempo
  1246.         subq.b    #1,d0
  1247.         add.w    d0,d0
  1248.         move.w    sttempo+2(pc,d0.w),d1
  1249.         bra.s    pushtempo
  1250. calctempo:    move.l    timerdiv(pc),d1
  1251.         divu    d0,d1
  1252. pushtempo:    movea.l    craddr+4(pc),a0
  1253.         move.b    d1,(a0)        ;and set the CIA timer
  1254.         lsr.w    #8,d1
  1255.         movea.l    craddr+8(pc),a0
  1256.         move.b    d1,(a0)
  1257.     ENDC
  1258.         rts ;   vv-- These values are the SoundTracker tempos (approx.)
  1259. sttempo:    dc.w    $0f00
  1260.     IFNE    CIAB
  1261.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  1262. timerdiv    dc.l    470000
  1263.     ENDC
  1264.  
  1265.     IFNE    MIDI
  1266. midicmds
  1267.     IFNE    HOLD
  1268.         tst.b    trk_noteoffcnt(a5)
  1269.         bmi.s    midi_nowaitoff
  1270.         subq.b    #1,trk_noteoffcnt(a5)
  1271.         bpl.s    midi_nowaitoff
  1272.         move.l    a5,a1
  1273.         move.b    trk_prevmidin(a5),d1
  1274.         beq.s    midi_nowaitoff    ;no note
  1275.         bsr.w    choff_midi
  1276. midi_nowaitoff:
  1277.     ENDC
  1278.         add.b    d6,d6    ;* 2
  1279.         move.w    midicmd_table(pc,d6.w),d0
  1280.         jmp    midifx(pc,d0.w)
  1281. midicmd_table:    dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  1282.         dc.w    mfx_05-midifx,endl-midifx,endl-midifx,endl-midifx,endl-midifx
  1283.         dc.w    mfx_0a-midifx,endl-midifx,endl-midifx,mfx_0d-midifx,mfx_0e-midifx
  1284.         dc.w    mfx_0f-midifx
  1285. midifx        
  1286. mfx_01        lea    prevmidipbend(pc),a0
  1287.         moveq    #0,d1
  1288.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  1289.         add.b    d1,d1        ;UWORD index
  1290.         tst.b    d4        ;x100??
  1291.         beq.s    resetpbend
  1292.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  1293.         lsl.w    #3,d4        ;multiply bend value by 8
  1294.         add.w    d4,d0
  1295.         cmp.w    #$3fff,d0
  1296.         bls.s    bendpitch
  1297.         move.w    #$3fff,d0
  1298. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  1299.         lsr.b    #1,d1        ;back to UBYTE
  1300.         or.b    #$e0,d1
  1301.         lea    noteondata(pc),a0
  1302.         move.b    d1,(a0)        ;midi command & channel
  1303.         move.b    d0,1(a0)    ;lower value
  1304.         and.b    #$7f,1(a0)    ;clear bit 7
  1305.         lsr.w    #7,d0
  1306.         and.b    #$7f,d0        ;clr bit 7
  1307.         move.b    d0,2(a0)    ;higher 7 bits
  1308.         moveq    #3,d0
  1309.         bsr.w    _AddMIDIData
  1310.         bra.w    endl
  1311.  
  1312. mfx_02        lea    prevmidipbend(pc),a0
  1313.         moveq    #0,d1
  1314.         move.b    trk_prevmidich(a5),d1
  1315.         add.b    d1,d1
  1316.         tst.b    d4
  1317.         beq.s    resetpbend    ;x200??
  1318.         move.w    0(a0,d1.w),d0
  1319.         lsl.w    #3,d4
  1320.         sub.w    d4,d0
  1321.         bpl.s    bendpitch    ;not under 0
  1322.         moveq    #0,d0
  1323.         bra.s    bendpitch
  1324. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  1325.         bne.w    endl
  1326.         move.w    #$2000,d0
  1327.         bra.s    bendpitch
  1328.  
  1329. mfx_03        tst.b    d3
  1330.         bne.w    endl
  1331.         lea    prevmidipbend(pc),a0
  1332.         moveq    #0,d1
  1333.         move.b    trk_prevmidich(a5),d1
  1334.         add.b    d1,d1
  1335.         move.b    d4,d0
  1336.         add.b    #128,d0
  1337.         lsl.w    #6,d0
  1338.         bra.s    bendpitch
  1339.  
  1340. mfx_0d        tst.b    d3
  1341.         bne.w    endl
  1342.         lea    noteondata+1(pc),a0    ;CHANNEL AFTERTOUCH
  1343.         move.b    d4,(a0)    ;value
  1344.         bmi.w    endl
  1345.         move.b    trk_prevmidich(a5),-(a0)
  1346.         or.b    #$d0,(a0)
  1347.         moveq    #2,d0
  1348.         bsr.w    _AddMIDIData
  1349.         bra.w    endl
  1350.  
  1351. mfx_0a        tst.b    d3
  1352.         bne.w    endl
  1353.         lea    noteondata+2(pc),a0    ;POLYPHONIC AFTERTOUCH
  1354.         and.b    #$7f,d4
  1355.         move.b    d4,(a0)
  1356.         move.b    trk_prevmidin(a5),-(a0)
  1357.         beq.w    endl
  1358.         move.b    trk_prevmidich(a5),-(a0)
  1359.         or.b    #$A0,(a0)
  1360.         moveq    #3,d0
  1361.         bsr.w    _AddMIDIData
  1362.         bra.w    endl
  1363.  
  1364. mfx_04        moveq    #$01,d0
  1365.         bra.s    pushctrldata
  1366.  
  1367. mfx_0e        moveq    #$0a,d0
  1368. pushctrldata    tst.b    d3        ;do it only once in a note
  1369.         bne.w    endl        ;(when counter = 0)
  1370.         lea    noteondata+2(pc),a0 ;push "control change" data,
  1371.         move.b    d4,(a0)        ;second databyte
  1372.         bmi.w    endl    ;I said 0 - $7f!!! (for future compability)
  1373.         move.b    d0,-(a0)    ;1st databyte
  1374.         move.b    trk_prevmidich(a5),-(a0)    ;MIDI channel
  1375.         or.b    #$b0,(a0)    ;command (B)
  1376.         moveq    #3,d0
  1377.         bsr.w    _AddMIDIData
  1378.         bra.w    endl
  1379.  
  1380. mfx_05        and.b    #$7f,d4        ;set contr. value of curr. MIDI ch.
  1381.         move.b    trk_prevmidich(a5),d6
  1382.         lea    midicontrnum(pc,d6.w),a0
  1383.         move.b    d4,(a0)
  1384.         bra.w    endl
  1385.  
  1386. mfx_0f        cmp.b    #$fa,d4        ;hold pedal ON
  1387.         bne.s    nomffa
  1388.         moveq    #$40,d0
  1389.         moveq    #$7f,d4
  1390.         bra.s    pushctrldata
  1391. nomffa        cmp.b    #$fb,d4        ;hold pedal OFF
  1392.         bne.s    nomffb
  1393.         moveq    #$40,d0
  1394.         moveq    #$00,d4
  1395.         bra.s    pushctrldata
  1396. nomffb        bra.w    fx_0f
  1397.  
  1398. mfx_00        tst.b    d4
  1399.         beq.w    endl
  1400.         and.b    #$7f,d4
  1401.         move.b    trk_prevmidich(a5),d6
  1402.         move.b    midicontrnum(pc,d6.w),d0
  1403.         bra.s    pushctrldata
  1404.  
  1405. midicontrnum    ds.b    16
  1406.  
  1407. _ResetMIDI:    movem.l    d2/a2,-(sp)
  1408.         lea    prevmidicpres(pc),a0
  1409.         clr.l    (a0)+    ;force presets to be set again
  1410.         clr.l    (a0)+    ;(clear prev. preset numbers)
  1411.         clr.l    (a0)+
  1412.         clr.l    (a0)
  1413.         clr.b    lastcmdbyte
  1414.         lea    midiresd(pc),a2
  1415.         move.b    #$e0,(a2)    ;reset pitchbenders & mod. wheel
  1416.         move.b    #$b0,3(a2)
  1417.         moveq    #15,d2
  1418. respbendl:    movea.l    a2,a0
  1419.         moveq    #6,d0
  1420.         bsr.w    _AddMIDIData
  1421.         addq.b    #1,(a2)
  1422.         addq.b    #1,3(a2)
  1423.         dbf    d2,respbendl
  1424.         lea    prevmidipbend(pc),a2
  1425.         moveq    #15,d2
  1426. resprevpbends:    move.w    #$2000,(a2)+
  1427.         dbf    d2,resprevpbends
  1428.         movem.l    (sp)+,d2/a2
  1429.         rts
  1430. midiresd:    dc.b    $e0,$00,$40,$b0,$01,$00
  1431.     ENDC
  1432.  
  1433. ; *************************************************************************
  1434. ; *************************************************************************
  1435. ; ***********          P U B L I C   F U N C T I O N S          ***********
  1436. ; *************************************************************************
  1437. ; *************************************************************************
  1438.  
  1439.     IFEQ    EASY
  1440.         xdef    _InitModule,_PlayModule,_PlayModule2
  1441.         xdef    _InitPlayer,_RemPlayer,_StopPlayer
  1442.         xdef    _SetTempo,_ContModule
  1443.     ENDC
  1444.     IFNE    EASY
  1445.  
  1446. ; This is the Reloc function, included only if EASY flag is set to 1.
  1447.  
  1448. reloci        move.l    24(a2),d0
  1449.         beq.s    xloci
  1450.         movea.l    d0,a0
  1451.         moveq   #0,d0
  1452.         move.b  787(a1),d0    ;number of samples
  1453.         subq.b  #1,d0
  1454. relocs:        bsr.s   relocentr
  1455.         move.l    -4(a0),d3    ;sample ptr
  1456.         beq.s    nosyn
  1457.         move.l    d3,a3
  1458.         tst.w    4(a3)
  1459.         bpl.s    nosyn        ;type >= 0
  1460.         move.w    20(a3),d2    ;number of waveforms
  1461.         lea    278(a3),a3    ;ptr to wf ptrs
  1462.         subq.w    #1,d2
  1463. relsyn:        add.l    d3,(a3)+
  1464.         dbf    d2,relsyn
  1465. nosyn:        dbf     d0,relocs
  1466. xloci        rts
  1467. norel        addq.l    #4,a0
  1468.         rts
  1469. relocentr:
  1470.         tst.l   (a0)
  1471.         beq.s   norel
  1472.         add.l   d1,(a0)+
  1473.         rts
  1474. _RelocModule:
  1475.         movem.l    a2-a3/d2-d3,-(sp)
  1476.         movea.l a0,a2
  1477.         move.l  a2,d1        ;d1 = ptr to start of module
  1478.         bsr.s    relocp
  1479.         movea.l 8(a2),a1
  1480.         bsr.s    reloci
  1481. rel_lp        bsr.s    relocb
  1482.         move.l    32(a2),d0    ;extension struct
  1483.         beq.s    rel_ex
  1484.         move.l    d0,a0
  1485.         bsr.s    relocentr    ;ptr to next module
  1486.         bsr.s    relocentr    ;InstrExt...
  1487.         addq.l    #4,a0        ;skip sizes of InstrExt
  1488. ; We reloc the pointers of MMD0exp, so anybody who needs them can easily
  1489. ; read them.
  1490.         bsr.s    relocentr    ;annotxt
  1491.         addq.l    #4,a0        ;annolen
  1492.         bsr.s    relocentr    ;InstrInfo
  1493.         addq.l    #8,a0
  1494.         bsr.s    relocentr    ;rgbtable (not useful for most people)
  1495.         addq.l    #4,a0        ;skip channelsplit
  1496.         bsr.s    relocentr    ;NotationInfo
  1497.         move.l    d0,a0
  1498.         move.l    (a0),d0
  1499.         beq.s    rel_ex
  1500.         move.l    d0,a2
  1501.         bsr.s    relocp
  1502.         movea.l 8(a2),a1
  1503.         bra.s    rel_lp
  1504. rel_ex        movem.l    (sp)+,d2-d3/a2-a3
  1505.         rts
  1506.  
  1507. relocb        move.l    16(a2),d0
  1508.         beq.s    xlocb
  1509.         movea.l    d0,a0
  1510.         move.w  504(a1),d0
  1511.         subq.b  #1,d0
  1512. rebl        bsr.s   relocentr
  1513.         dbf     d0,rebl
  1514. xlocb        rts
  1515.  
  1516. relocp        lea    8(a2),a0
  1517.         bsr.s    relocentr
  1518.         addq.l    #4,a0
  1519.         bsr.s    relocentr
  1520.         addq.l    #4,a0
  1521.         bsr.s    relocentr
  1522.         addq.l    #4,a0
  1523.         bra.s    relocentr
  1524.  
  1525.     ENDC
  1526.  
  1527.  
  1528. ; *************************************************************************
  1529. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.00 module
  1530. ; *************************************************************************
  1531.  
  1532. _InitModule:    movem.l    a2-a3/d2,-(sp)
  1533.         move.l    a0,d0
  1534.         beq.s    IM_exit            ;0 => xit
  1535.     IFNE    RELVOL
  1536.         movea.l    mmd_songinfo(a0),a1    ;MMD0song
  1537.         move.b    msng_mastervol(a1),d0    ;d0 = mastervol
  1538.         ext.w    d0
  1539.         lea    msng_trkvol(a1),a1    ;a1 = trkvol
  1540.         lea    trackdataptrs(pc),a2
  1541.         moveq    #15,d1
  1542. IM_loop0    move.b    (a1)+,d2    ;get vol...
  1543.         ext.w    d2
  1544.         move.l    (a2)+,a3    ;pointer to track data
  1545.         mulu    d0,d2        ;mastervol * trackvol
  1546.         lsr.w    #4,d2
  1547.         move.w    d2,trk_trackvol(a3)
  1548.         dbf    d1,IM_loop0
  1549.     ENDC
  1550.         lea    holdvals(pc),a2
  1551.         movea.l    a0,a3
  1552.         move.l    mmd_expdata(a0),d0    ;expdata...
  1553.         beq.s    IM_clrhlddec        ;none here
  1554.         move.l    d0,a1
  1555.         move.l    4(a1),d0        ;exp_smp
  1556.         beq.s    IM_clrhlddec    ;again.. nothing
  1557.         move.l    d0,a0        ;InstrExt...
  1558.         move.w    8(a1),d2    ;# of entries
  1559.         beq.s    IM_clrhlddec
  1560.         subq.w    #1,d2        ;- 1 (for dbf)
  1561.         move.w    10(a1),d0    ;entry size
  1562.     IFNE    MIDI
  1563.         movea.l    mmd_songinfo(a3),a3    ;MMD0song
  1564.     ENDC
  1565. IM_loop1
  1566.     IFNE    MIDI
  1567.         cmp.w    #2,d0
  1568.         ble.s    IM_nsmnoff
  1569.         tst.b    2(a0)        ;suppress MIDI note off?
  1570.         beq.s    IM_nsmnoff
  1571.         bset    #7,inst_midich(a3)
  1572. IM_nsmnoff    addq.l    #8,a3        ;next instr
  1573.     ENDC
  1574.         move.b    1(a0),63(a2)    ;InstrExt.decay ->decay
  1575.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  1576.         adda.w    d0,a0        ;ptr to next InstrExt
  1577.         dbf    d2,IM_loop1
  1578.         bra.s    IM_exit
  1579. IM_clrhlddec    move.w    #3*63,d0        ;no InstrExt => clear holdvals/decays
  1580. IM_loop2    clr.b    (a2)+
  1581.         dbf    d0,IM_loop2
  1582. IM_exit        movem.l    (sp)+,a2-a3/d2
  1583.         rts
  1584. ; *************************************************************************
  1585. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  1586. ; *************************************************************************
  1587. _InitPlayer:
  1588.     IFNE    MIDI
  1589.         bsr.w    _GetSerial
  1590.         tst.l    d0
  1591.         bne.s    IP_error
  1592.     ENDC
  1593.         bsr.w    _AudioInit
  1594.         tst.l    d0
  1595.         bne.s    IP_error
  1596.         moveq    #33,d0
  1597.         bsr.w    _SetTempo    ;set default tempo
  1598.         moveq    #0,d0
  1599.         rts
  1600. IP_error    bsr.s    _RemPlayer
  1601.         moveq    #-1,d0
  1602.         rts
  1603. ; *************************************************************************
  1604. ; RemPlayer() -- free interrupt, audio, serial port etc..
  1605. ; *************************************************************************
  1606. _RemPlayer:    move.b    _timeropen(pc),d0
  1607.         beq.s    RP_notimer    ;timer is not ours
  1608.         bsr.s    _StopPlayer
  1609. RP_notimer:    bsr.w    _AudioRem
  1610.     IFNE    MIDI
  1611.         bsr.w    _FreeSerial
  1612.     ENDC
  1613.         rts
  1614. ; *************************************************************************
  1615. ; StopPlayer() -- stop music
  1616. ; *************************************************************************
  1617. _StopPlayer:    move.b    _timeropen(pc),d0
  1618.         beq.s    SP_end        ;res. alloc fail.
  1619.     IFNE    CIAB
  1620.         movea.l    craddr(pc),a0
  1621.         bclr    #0,(a0)        ;stop timer
  1622.     ENDC
  1623.         move.l    _module(pc),d0
  1624.         beq.s    SP_nomod
  1625.         move.l    d0,a0
  1626.         clr.w    mmd_pstate(a0)
  1627.         clr.l    _module
  1628. SP_nomod
  1629.     IFNE    MIDI
  1630.         clr.b    lastcmdbyte
  1631.     ENDC
  1632.         bsr.w    SoundOff
  1633. SP_end        rts
  1634.  
  1635.  
  1636. _ContModule    move.b    _timeropen(pc),d0
  1637.         beq.s    SP_end
  1638.         movea.l    craddr(pc),a1
  1639.         bclr    #0,(a1)
  1640.         move.l    a0,-(sp)
  1641.         bsr.w    SoundOff
  1642.         move.l    (sp)+,a0
  1643.         moveq    #0,d0
  1644.         bra.s    contpoint
  1645. ; *************************************************************************
  1646. ; PlayModule(a0 = module)  -- initialize & play it!!
  1647. ; PlayModule2(a0 = module) -- play module (must be initialized)
  1648. ; *************************************************************************
  1649. _PlayModule:    st    d0
  1650. contpoint    movem.l    a0/d0,-(sp)
  1651.         bsr    _InitModule
  1652.         movem.l    (sp)+,a0/d0
  1653. _PlayModule2:    move.b    _timeropen(pc),d1
  1654.         beq.s    SP_end        ;resource allocation failure
  1655.         move.l    a0,d1
  1656.         beq.s    SP_end        ;module failure
  1657.     IFNE    CIAB
  1658.         movea.l    craddr(pc),a1
  1659.         bclr    #0,(a1)        ;stop timer...
  1660.     ENDC
  1661.         clr.l    _module
  1662.     IFNE    MIDI
  1663.         clr.b    lastcmdbyte
  1664.     ENDC
  1665.         move.w    _modnum,d1
  1666.         beq.s    PM_modfound
  1667. PM_nextmod    tst.l    mmd_expdata(a0)
  1668.         beq.s    PM_modfound
  1669.         move.l    mmd_expdata(a0),a1
  1670.         tst.l    (a1)
  1671.         beq.s    PM_modfound        ;no more modules here!
  1672.         move.l    (a1),a0
  1673.         subq.w    #1,d1
  1674.         bgt.s    PM_nextmod
  1675. PM_modfound    movea.l    mmd_songinfo(a0),a1        ;song
  1676.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  1677.         btst    #0,msng_flags(a1)
  1678.         bne.s    PM_filon
  1679.         bset    #1,$bfe001
  1680.         bra.s    PM_filset
  1681. PM_filon    bclr    #1,$bfe001
  1682. PM_filset    tst.b    d0
  1683.         beq.s    PM_noclr
  1684.         clr.l    mmd_pline(a0)
  1685. PM_noclr    move.w    mmd_pseqnum(a0),d1
  1686.         add.w    #msng_playseq,d1
  1687.         move.b    0(a1,d1.w),d1        ;get first playseq entry
  1688.         move.b    d1,mmd_pblock+1(a0)
  1689.         move.w    #-1,mmd_pstate(a0)
  1690.         move.l    a0,_module
  1691.     IFNE    CIAB
  1692.         move.w    msng_deftempo(a1),d0    ;get default tempo
  1693.         movea.l    craddr(pc),a1
  1694.         bsr.w    _SetTempo    ;set default tempo
  1695.         bset    #0,(a1)        ;start timer => PLAY!!
  1696.     ENDC
  1697. PM_end        rts
  1698. ; *************************************************************************
  1699.  
  1700. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  1701.         moveq    #0,d2
  1702.         movea.l    4,a6
  1703. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  1704.     IFNE    AUDDEV
  1705.         addq.l    #1,d2
  1706.         moveq    #-1,d0
  1707.         jsr    -$14a(a6)    ;AllocSignal()
  1708.         tst.b    d0
  1709.         bmi.w    initerr
  1710.         move.b    d0,sigbitnum
  1711. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  1712.         lea    allocport(pc),a1
  1713.         move.b    d0,15(a1)    ;set mp_SigBit
  1714.         move.l    a1,-(sp)
  1715.         suba.l    a1,a1
  1716.         jsr    -$126(a6)    ;FindTask(0)
  1717.         move.l    (sp)+,a1
  1718.         move.l    d0,16(a1)    ;set mp_SigTask
  1719.         lea    reqlist(pc),a0
  1720.         move.l    a0,(a0)        ;NEWLIST begins...
  1721.         addq.l    #4,(a0)
  1722.         clr.l    4(a0)
  1723.         move.l    a0,8(a0)    ;NEWLIST ends...
  1724. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  1725.         addq.l    #1,d2
  1726.         lea    allocreq(pc),a1
  1727.         lea    audiodevname(pc),a0
  1728.         moveq    #0,d0
  1729.         moveq    #0,d1
  1730.         jsr    -$1bc(a6)    ;OpenDevice()
  1731.         tst.b    d0
  1732.         bne.w    initerr
  1733.         st.b    audiodevopen
  1734. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open ciaa.resource
  1735.         addq.l    #1,d2
  1736.     ENDC
  1737.     IFNE    CIAB
  1738.         cmp.b    #50,$212(a6)    ;ExecBase->VBlankFrequency
  1739.         beq.s    init_pal
  1740.         move.l    #474326,timerdiv ;Assume that CIA freq is 715 909 Hz
  1741. init_pal    moveq    #0,d0
  1742.         lea    ciabname(pc),a1
  1743.         jsr    -$1f2(a6)    ;OpenResource()
  1744.         tst.l    d0
  1745.         beq.s    initerr
  1746.         move.l    d0,_ciaresource
  1747. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  1748.         addq.l    #1,d2
  1749.         moveq    #2,d3
  1750.         lea    craddr(pc),a4
  1751.         move.l    #$bfdf00,(a4)+    ;Initialize Timer B addresses
  1752.         move.l    #$bfd600,(a4)+
  1753.         move.l    #$bfd700,(a4)
  1754.         move.l    d0,a6
  1755.         lea    timerinterrupt(pc),a1    ;Attempt to get timer B
  1756.         moveq    #1,d0    ;Bit number 1: Timer B
  1757.         jsr    -$6(a6)    ;AddICRVector
  1758.         tst.l    d0
  1759.         beq.s    gotTimerB        ;succeeded!!
  1760.         moveq    #1,d3
  1761.         lea    timerinterrupt(pc),a1    ;no. Get timer A then...
  1762.         moveq    #0,d0    ;Bit number 0: Timer A
  1763.         jsr    -$6(a6)
  1764.         tst.l    d0
  1765.         bne.s    initerr
  1766.         move.l    #$bfd500,(a4)        ;Set Timer A addresses
  1767.         move.l    #$bfd400,-(a4)
  1768.         move.l    #$bfde00,-(a4)
  1769. gotTimerB:    movea.l    craddr(pc),a0    ;get Control Register address
  1770.         and.b    #%10000000,(a0) ;clear CtrlReg bits 0 - 6
  1771.         move.b    d3,_timeropen    ;d3: 1 = TimerA 2 = TimerB
  1772.     ENDC
  1773.     IFNE    VBLANK
  1774.         moveq    #5,d0        ;INTB_VERTB
  1775.         lea    timerinterrupt(pc),a1
  1776.         jsr    -$a8(a6)    ;AddIntServer
  1777.         st    _timeropen
  1778.     ENDC
  1779.         moveq    #0,d0
  1780. initret:    movem.l    (sp)+,a4/a6/d2-d3
  1781.         rts
  1782. initerr:    move.l    d2,d0
  1783.         bra.s    initret
  1784.  
  1785. _AudioRem:    move.l    a6,-(sp)
  1786.         moveq    #0,d0
  1787.         move.b    _timeropen(pc),d0
  1788.         beq.s    rem1
  1789. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  1790.         clr.b    _timeropen
  1791.     IFNE    CIAB
  1792.         move.l    _ciaresource,a6
  1793.         lea    timerinterrupt(pc),a1
  1794.         subq.b    #1,d0
  1795.         jsr    -$c(a6)        ;RemICRVector
  1796.     ENDC
  1797.     IFNE    VBLANK
  1798.         movea.l    4,a6
  1799.         lea    timerinterrupt(pc),a1
  1800.         moveq    #5,d0
  1801.         jsr    -$ae(a6)    ;RemIntServer
  1802.     ENDC
  1803. rem1:
  1804.     IFNE    AUDDEV
  1805.         movea.l    4,a6
  1806.         tst.b    audiodevopen
  1807.         beq.s    rem2
  1808.         move.w    #$000f,$dff096    ;stop audio DMA
  1809. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  1810.         lea    allocreq(pc),a1
  1811.         jsr    -$1c2(a6)    ;CloseDevice()
  1812.         clr.b    audiodevopen
  1813. rem2:        moveq    #0,d0
  1814.         move.b    sigbitnum(pc),d0
  1815.         bmi.s    rem3
  1816. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  1817.         jsr    -$150(a6)    ;FreeSignal()
  1818.     ENDC
  1819. rem3:        move.l    (sp)+,a6
  1820.         rts
  1821.  
  1822.     IFNE    MIDI
  1823. _GetSerial:    move.l    a6,-(sp)    ;Get serial port for MIDI
  1824.         bsr.s    GetSer2
  1825.         tst.l    d0        ;got the port??
  1826.         beq.s    rgser        ;yes
  1827.         movea.l    4,a6        ;no..try to flush serial.device:
  1828.         jsr    -$84(a6)        ;Forbid
  1829.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  1830.         lea    serdev(pc),a1        ;"serial.device"
  1831.         jsr    -$114(a6)        ;FindName
  1832.         tst.l    d0
  1833.         beq.s    serdnotf        ;no serial.device!!
  1834.         move.l    d0,a1
  1835.         jsr    -$1b6(a6)        ;RemDevice
  1836. serdnotf:    jsr    -$8a(a6)        ;and Permit
  1837.         bsr.s    GetSer2        ;now try it again...
  1838. rgser:        move.l    (sp)+,a6
  1839.         rts
  1840.  
  1841. GetSer2:    movea.l    4,a6
  1842.         moveq    #0,d0
  1843.         lea    miscresname(pc),a1
  1844.         jsr    -$1f2(a6)    ;OpenResource()
  1845.         move.l    d0,miscresbase
  1846.         tst.l    d0
  1847.         beq.s    gserror
  1848.         move.l    d0,a6
  1849.         lea    medname(pc),a1
  1850.         moveq    #0,d0        ;serial port
  1851.         jsr    -$6(a6)        ;AllocMiscResource()
  1852.         tst.l    d0
  1853.         bne.s    gserror
  1854.         moveq    #0,d0        ;TBE
  1855.         lea    serinterrupt(pc),a1
  1856.         move.l    4,a6
  1857.         jsr    -$a2(a6)    ;SetIntVector()
  1858.         move.l    d0,prevtbe
  1859.         move.w    #$8001,$dff09a    ;TBE on!!
  1860.         move.w    #114,$dff032    ;set baud rate (SERPER)
  1861.         st.b    serportalloc
  1862.         moveq    #0,d0
  1863.         rts
  1864. gserror:    moveq    #-1,d0
  1865.         rts
  1866.  
  1867.  
  1868. _FreeSerial:    move.l    a6,-(sp)
  1869.         tst.l    miscresbase
  1870.         beq.s    retfs
  1871.         tst.b    serportalloc
  1872.         beq.s    retfs
  1873.         movea.l    4,a6
  1874.         tst.b    $126(a6)    ;interrupts disabled?
  1875.         bge.s    fs_skipwait    ;yes, can't busy loop...
  1876. fs_waitempty    move.b    buffempty(pc),d0
  1877.         beq.s    fs_waitempty
  1878. fs_skipwait    move.w    #$0001,$dff09a    ;disable TBE
  1879.         move.l    prevtbe(pc),a1
  1880.         moveq    #0,d0
  1881.         jsr    -$a2(a6)    ;SetIntVector()
  1882. fs_noptbe    movea.l    miscresbase(pc),a6
  1883.         moveq    #0,d0        ;serial port
  1884.         jsr    -$c(a6)        ;FreeMiscResource()
  1885.         clr.b    serportalloc
  1886.         clr.b    lastcmdbyte
  1887. retfs:        move.l    (sp)+,a6
  1888.         rts
  1889.  
  1890. prevtbe:    dc.l    0
  1891.  
  1892. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable...
  1893.         addq.b    #1,$126(a6)    (Interrupts are enabled anyway...)
  1894.         move.w    #1,$9c(a0)    ;clear intreq bit
  1895.         move.b    8(a1),d0    ;bytesinbuff
  1896.         beq.s    sih_buffe    ;buffer empty
  1897.         movea.l    4(a1),a5    ;get buffer read pointer
  1898.         move.w    #$100,d1    ;Stop bit
  1899.         move.b    (a5)+,d1    ;get byte
  1900.         move.w    d1,$30(a0)    ;and push it out!! (SERDAT)
  1901.         cmpa.l    a1,a5        ;shall we reset ptr??
  1902.         bne.s    norrbuffptr    ;not yet..
  1903.         lea    sendbuffer(pc),a5
  1904. norrbuffptr:    subq.b    #1,d0        ;one less bytes in buffer
  1905.         move.b    d0,8(a1)    ;remember it
  1906.         move.l    a5,4(a1)    ;push new read pointer back
  1907. exsih:        subq.b    #1,$126(a6)
  1908.         bge.s    exsih0
  1909.         move.w    #$c000,$9a(a0)
  1910. exsih0:        rts
  1911. sih_buffe    st    9(a1)
  1912.         bra.s    exsih
  1913.  
  1914. _AddMIDIData:    tst.b    serportalloc
  1915.         beq.s    retamd
  1916.         movem.l    a2/a6,-(sp)
  1917.         movea.l    4,a6
  1918.         move.w    #$4000,$dff09a    ;Disable interrupts
  1919.         addq.b    #1,$126(a6)    ;ExecBase->IDNestCnt
  1920.         lea    buffptr(pc),a2    ;end of buffer (ptr)
  1921.         tst.b    9(a2)
  1922.         beq.s    noTBEreq
  1923.         clr.b    9(a2)
  1924.         move.w    #$8001,$dff09c    ;request TBE
  1925. noTBEreq    movea.l    (a2),a1        ;buffer pointer
  1926. adddataloop:    move.b    (a0)+,d1    ;get byte
  1927.         bpl.s    norscheck    ;this isn't a status byte
  1928.         cmp.b    #$ef,d1        ;forget system messages
  1929.         bhi.s    norscheck
  1930.         cmp.b    lastcmdbyte(pc),d1 ;same as previos status byte??
  1931.         beq.s    samesb        ;yes, skip
  1932.         move.b    d1,10(a2)    ;no, don't skip but remember!!
  1933. norscheck:    move.b    d1,(a1)+    ;push it to midi send buffer
  1934.         addq.b    #1,8(a2)
  1935. samesb:        cmpa.l    a2,a1    ;end of buffer??
  1936.         bne.s    noresbuffptr    ;no, no!!
  1937.         lea    sendbuffer(pc),a1 ;better reset it to avoid trashing
  1938. noresbuffptr:    subq.b    #1,d0
  1939.         bne.s    adddataloop
  1940.         move.l    a1,(a2)        ;push new buffer ptr back
  1941.         subq.b    #1,$126(a6)
  1942.         bge.s    retamd1
  1943.         move.w    #$c000,$dff09a    ;enable interrupts again
  1944. retamd1        movem.l    (sp)+,a2/a6
  1945. retamd        rts
  1946. sendbuffer    ds.b    128
  1947. buffptr        dc.l    sendbuffer
  1948. readbuffptr    dc.l    sendbuffer
  1949. bytesinbuff    dc.b    0
  1950. buffempty    dc.b    -1
  1951. lastcmdbyte    dc.b    0
  1952.     ENDC
  1953.     IFNE    AUDDEV
  1954. sigbitnum    dc.b    -1
  1955.     ENDC
  1956.         EVEN
  1957.     IFNE    AUDDEV
  1958. audiodevopen    dc.b    0
  1959.     ENDC
  1960. serportalloc    dc.b    0
  1961. _timeropen    dc.b    0
  1962.         even
  1963.     IFNE    MIDI
  1964. preschgdata    dc.w    0
  1965. noteondata    dc.l    0
  1966. miscresbase    dc.l    0
  1967.     ENDC
  1968. dmaonmsk    dc.w    0
  1969.     IFNE    MIDI
  1970. bytesinnotebuff    dc.w    0
  1971. noteonbuff    ds.b    18*3
  1972.     ENDC
  1973.         even
  1974.     IFNE    CIAB
  1975. _ciaresource    dc.l    0
  1976. craddr        dc.l    0
  1977.         dc.l    0    ;tloaddr
  1978.         dc.l    0    ;thiaddr
  1979.     ENDC
  1980. _module:    dc.l    0
  1981. timerinterrupt    dc.w    0,0,0,0,0
  1982.         dc.l    timerintname,serportalloc,_IntHandler
  1983.     IFNE    MIDI
  1984. serinterrupt    dc.w    0,0,0,0,0
  1985.         dc.l    serintname,buffptr,SerIntHandler
  1986.     ENDC
  1987.     IFNE    AUDDEV
  1988. allocport    dc.l    0,0    ;succ, pred
  1989.         dc.b    4,0    ;NT_MSGPORT
  1990.         dc.l    0    ;name
  1991.         dc.b    0,0    ;flags = PA_SIGNAL
  1992.         dc.l    0    ;task
  1993. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  1994.         dc.b    5,0
  1995. allocreq    dc.l    0,0
  1996.         dc.b    5,127    ;NT_MESSAGE, use maximum priority (127)
  1997.         dc.l    0,allocport    ;name, replyport
  1998.         dc.w    68        ;length
  1999.         dc.l    0    ;io_Device
  2000.         dc.l    0    ;io_Unit
  2001.         dc.w    0    ;io_Command
  2002.         dc.b    0,0    ;io_Flags, io_Error
  2003.         dc.w    0    ;ioa_AllocKey
  2004.         dc.l    sttempo    ;ioa_Data
  2005.         dc.l    1    ;ioa_Length
  2006.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  2007.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  2008. audiodevname    dc.b    'audio.device',0
  2009.     ENDC
  2010.     IFNE    CIAB
  2011. ciabname    dc.b    'ciab.resource',0
  2012.     ENDC
  2013. timerintname    dc.b    'MEDTimerInterrupt',0
  2014.     IFNE    MIDI
  2015. serintname    dc.b    'MEDSerialInterrupt',0
  2016. miscresname    dc.b    'misc.resource',0
  2017. serdev        dc.b    'serial.device',0
  2018. medname        dc.b    'MED modplayer',0 ;yeah, our name
  2019.     ENDC
  2020.  
  2021.     IFNE    SYNTH
  2022. _synthper:    dc.w 3424,3232,3048,2880,2712,2560,2416,2280,2152,2032
  2023.         dc.w 1920,1812,1712,1616,1524,1440,1356,1280,1208,1140
  2024.         dc.w 1076,1016,960,906
  2025.     ENDC
  2026. _periods:    dc.w 856,808,762,720,678,640,604,570,538,508,480,453
  2027.         dc.w 428,404,381,360,339,320,302,285,269,254,240,226
  2028.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2029.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2030.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2031.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2032.  
  2033. holdvals:    ds.b 63
  2034. decays:        ds.b 63
  2035.  
  2036.     IFND    __G2
  2037.         section "datachip",data,chip ;for A68k
  2038.     ENDC
  2039.     IFD    __G2
  2040.         section "datachip",data_c ;this is for Devpac 2
  2041.     ENDC
  2042.         xdef    _modnum
  2043.     IFNE    EASY
  2044. easymod        incbin    "module"    ;<<<<< MODULE NAME HERE!
  2045.     ENDC
  2046. _chipzero:    dc.l    0
  2047. _modnum:    dc.w    0    ;number of module to play
  2048.  
  2049. ; the track-data structure definition:
  2050. trk_prevnote    equ    0    ;previous note number
  2051. trk_previnstr    equ    1    ;previous instrument number
  2052. trk_prevvol    equ    2    ;previous volume
  2053. trk_prevmidich    equ    3    ;previous MIDI channel
  2054. trk_cmd        equ    4    ;command (the 3rd number from right)
  2055. trk_cmdqual    equ    5    ;command qualifier (infobyte, databyte..)
  2056. trk_prevmidin    equ    6    ;previous MIDI note
  2057. trk_noteoffcnt    equ    7    ;note-off counter (hold)
  2058. trk_inithold    equ    8    ;default hold for this instrument
  2059. trk_initdecay    equ    9    ;default decay for....
  2060. trk_stransp    equ    10    ;instrument transpose
  2061. trk_pad0    equ    11
  2062. trk_previnstra    equ    12    ;address of the previous instrument data
  2063. trk_trackvol    equ    16
  2064. ;    the following data only on tracks 0 - 3
  2065. trk_prevper    equ    18    ;previous period
  2066. trk_audioaddr    equ    20    ;hardware audio channel base address
  2067. trk_sampleptr    equ    24    ;pointer to sample
  2068. trk_samplelen    equ    28    ;length (>> 1)
  2069. trk_porttrgper    equ    30    ;portamento (cmd 3) target period
  2070. trk_vibroffs    equ    32    ;vibrato table offset
  2071. trk_vibrspdsz    equ    33    ;vibrato speed/size (cmd 4 qualifier)
  2072. trk_synthptr    equ    34    ;pointer to synthetic/hybrid instrument
  2073. trk_arpgoffs    equ    38    ;SYNTH: current arpeggio offset
  2074. trk_arpsoffs    equ    40    ;SYNTH: arpeggio restart offset
  2075. trk_volxcnt    equ    42    ;SYNTH: volume execute counter
  2076. trk_wfxcnt    equ    43    ;SYNTH: waveform execute counter
  2077. trk_volcmd    equ    44    ;SYNTH: volume command pointer
  2078. trk_wfcmd    equ    46    ;SYNTH: waveform command pointer
  2079. trk_volwait    equ    48    ;SYNTH: counter for WAI (volume list)
  2080. trk_wfwait    equ    49    ;SYNTH: counter for WAI (waveform list)
  2081. trk_synthvibspd    equ    50    ;SYNTH: vibrato speed
  2082. trk_wfchgspd    equ    52    ;SYNTH: period change
  2083. trk_perchg    equ    54    ;SYNTH: curr. period change from trk_prevper
  2084. trk_envptr    equ    56    ;SYNTH: envelope waveform pointer
  2085. trk_synvibdep    equ    60    ;SYNTH: vibrato depth
  2086. trk_synvibwf    equ    62    ;SYNTH: vibrato waveform
  2087. trk_synviboffs    equ    66    ;SYNTH: vibrato pointer
  2088. trk_initvolxspd    equ    68    ;SYNTH: volume execute speed
  2089. trk_initwfxspd    equ    69    ;SYNTH: waveform execute speed
  2090. trk_volchgspd    equ    70    ;SYNTH: volume change
  2091. trk_prevnote2    equ    71    ;SYNTH: previous note
  2092. trk_synvol    equ    72    ;SYNTH: current volume
  2093. trk_synthtype    equ    73    ;>0 = synth, -1 = hybrid, 0 = no synth
  2094. trk_periodtbl    equ    74    ;pointer to period table
  2095. trk_prevportspd    equ    78    ;portamento (cmd 3) speed
  2096. trk_decay    equ    80    ;decay
  2097. trk_fadespd    equ    81    ;decay speed
  2098. trk_envrestart    equ    82    ;SYNTH: envelope waveform restart point
  2099. trk_envcount    equ    86    ;SYNTH: envelope counter
  2100. trk_split    equ    87    ;0 = this channel not splitted (OctaMED V2)
  2101.         end
  2102.